package com.xshbbs.tool;

import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Base64;
import java.util.Random;

import javax.servlet.http.HttpServletRequest;

import sun.misc.BASE64Encoder;

/**
 * 
 * <p>Title: TokenProccessor</p>  
 * <p>Description: 生成Token的工具类</p>  
 * @author  朱子佳  
 * @date  2019年5月24日
 */
public class TokenProccessor {
	
	/*
	*单例设计模式（保证类的对象在内存中只有一个）
	*1、把类的构造函数私有
	*2、自己创建一个类的对象
	*3、对外提供一个公共的方法，返回类的对象
	*/
	private TokenProccessor() {
		
	}
	
	private static final TokenProccessor instance = new TokenProccessor();
    
    /**
     * 返回类的对象
     * @return
     */
    public static TokenProccessor getInstance(){
        return instance;
    }
    
    /**
     * 生成Token
     * Token：Nv6RRuGEVvmGjB+jimI/gw==
     * @return
     */
    public String makeToken(){  //checkException
        //  7346734837483  834u938493493849384  43434384
    	//System.currentTimeMillis()：返回以毫秒为单位的当前时间
    	//Random().nextInt(999999999))：返回一个伪随机数，为0-999999999之间均匀分布的int值
    	String token = (System.currentTimeMillis() + new Random().nextInt(999999999)) + "";
        //数据指纹   128位长   16个字节  md5
        try {
        	//MessageDigest.getInstance("md5")：返回实现指定摘要算法的 MessageDigest 对象。 
            MessageDigest md = MessageDigest.getInstance("md5");
            //使用指定的 byte 数组对摘要进行最后更新，然后完成摘要计算。也就是说，此方法首先调用 update(input)，向 update 方法传递 input 数组，然后调用 digest()。 
            byte md5[] =  md.digest(token.getBytes());
            //base64编码--任意二进制编码明文字符   adfsdfsdfsf
//            BASE64Encoder encoder = new BASE64Encoder();
//            return encoder.encode(md5);
            
            //Base64.getEncoder()：返回一个Base64.Encoder编码使用Basic型base64编码方案。 
            //encodeToString()：使用Base64编码方案将指定的字节数组编码为字符串。
            return Base64.getEncoder().encodeToString(token.getBytes());
        } catch (NoSuchAlgorithmException e) {
            throw new RuntimeException(e);
        }
    }
	
    /**
	 * 判断客户端提交上来的令牌和服务器端生成的令牌是否一致
	 * @param request
	 * @return 
	 * 			true 用户重复提交了表单
	 * 			false 用户没有重复提交表单
	 */
	public static boolean isRepeatSubmit(HttpServletRequest request) {
		
		//如果用户提交的表单中没有token，则用户重复提交了表单
		String client_token = request.getParameter("token");
		if(client_token == null) {
			return true;
		}
		//如果当前用户的Session中不存在token，则用户重复提交了表单
		String server_token = (String) request.getSession().getAttribute("token");
		if(server_token == null) {
			return true;
		}
		//如果存储在Session中的token与表单提交的token不同，则用户重复提交了表单
		if(!server_token.equals(client_token)) {
			return true;
		}
		request.getSession().removeAttribute("token");//移除session中的token
		return false;
		
	}
    
}
